/*
 * ModuleManager.cpp
 *
 *  Created on: 01.05.2009
 *      Author: h3llfire
 */

#include "ModuleManager.h"
#include <wx/log.h>

namespace Impp {


ModuleInfo::ModuleInfo(const wxString & moduleClassName, const wxString & interfaceClassName) :
	moduleClassName(moduleClassName),
	interfaceClassName(interfaceClassName),
	module(NULL),
	inited(false)
{

}

const wxString& ModuleInfo::getInterfaceClassName() const{
	return interfaceClassName;
}

const wxString & ModuleInfo::getClassName() const{
	return moduleClassName;
}

iModule* ModuleInfo::getModule() const{
	return module;
}

bool ModuleInfo::loadModule(){
	wxObject* object = wxCreateDynamicObject(moduleClassName);
	if(object == NULL){
		wxLogDebug(wxT("ModuleInfo::loadModule: Coudn't load Module with className: %s! Class not found!"), moduleClassName.c_str());
		return false;
	}
	module = dynamic_cast<iModule*>(object);
	if(module != NULL){
		//wxLogDebug(wxT("Module %s loaded"), interfaceClassName.c_str());
		return true;
	}else{
		wxLogDebug(wxT("ModuleInfo::loadModule: Coudn't load Module with className: %s! Class coudn't be cast to iModule!"), moduleClassName.c_str());
		delete object;
		return false;
	}
}

void ModuleInfo::initModule(){
	wxASSERT(module != NULL);
	wxASSERT(!inited);
	module->moduleInit();
	inited = true;
}

void ModuleInfo::destroyModule(){
	wxASSERT(module != NULL);
	module->moduleDestroy();
	delete module;
	module = NULL;
}

bool ModuleInfo::isLoaded() const{
	return module != NULL;
}

bool ModuleInfo::isInited() const{
	return inited;
}


iProtocol* ProtocolInfo::createAndInitInstance(Account* account){

	wxObject* object = wxCreateDynamicObject(className);

	if(object == NULL){
		wxLogDebug(wxT("ProtocolInfo::createAndInitInstance: Coudn't load Protocol with className: %s! Class not found!"), className.c_str());
		return NULL;
	}
	iProtocol* prot = dynamic_cast<iProtocol*>(object);
	if(prot != NULL){
		prot->init(account);
		return prot;
	}else{
		wxLogDebug(wxT("ProtocolInfo::createAndInitInstance: Coudn't load Protocol with className: %s! Class coudn't be cast to iProtocol!"), className.c_str());
		delete object;
		return NULL;
	}

}

ModuleManager::ModuleManager() {
	addAvailableModul(wxT("StdChatWindowModule"), MODULE_INTERFACE_CHATWINDOW);
	addAvailableModul(wxT("StdBuddyListModule"), MODULE_INTERFACE_BUDDYLIST);
	addAvailableModul(wxT("StdUserInterfaceModule"), MODULE_INTERFACE_USERINTERFACE);

	addAvailableModul(wxT("StdPopupModule"), MODULE_INTERFACE_MODULE);
	addAvailableModul(wxT("StdTaskBarIconModule"), MODULE_INTERFACE_MODULE);
	addAvailableModul(wxT("StdBirthdayModule"), MODULE_INTERFACE_MODULE);
	addAvailableModul(wxT("StdRichTextChatLogModule"), wxT("iChatLogFactory"));
	addAvailableModul(wxT("StdSmileyThemeManager"), wxT("iSmileyThemeManager"));
	addAvailableModul(wxT("StdHistoryModule"), MODULE_INTERFACE_MODULE);
	addAvailableModul(wxT("StdUserInfoDialogModule"), MODULE_INTERFACE_MODULE);
	addAvailableModul(wxT("StdSettingsDialogModule"), MODULE_INTERFACE_MODULE);
	addAvailableModul(wxT("StdImportExportModule"), MODULE_INTERFACE_MODULE);
	addAvailableModul(wxT("StdNowPlayingModule"), MODULE_INTERFACE_MODULE);
	addAvailableModul(wxT("StdVariableModule"), MODULE_INTERFACE_MODULE);


	addAvailableProtocol(wxT("Oscar"));

}

ModuleManager::~ModuleManager() {
	destroyCoreInterfaceModules();
	destroyOtherModules();

	std::vector<ModuleInfo*>::iterator i;
	for(i = modules.begin(); i != modules.end(); i++){
		ModuleInfo* m = *i;
		delete m;
	}

	std::vector<ProtocolInfo*>::iterator p;
	for(p = protInfos.begin(); p != protInfos.end(); p++){
		ProtocolInfo* info = *p;
		delete info;
	}
}

void ModuleManager::loadBuddyListModule(){
	if(buddyListModuleInfo != NULL){
		buddyListModuleInfo->loadModule();
	}else{
		wxLogDebug(wxT("No BuddyListModule found!"));
	}
}

void ModuleManager::loadUserInterfaceModule(){
	if(userInterfaceModuleInfo != NULL){
		userInterfaceModuleInfo->loadModule();
	}else{
		wxLogDebug(wxT("No UserInterfaceModule found!"));
	}
}

void ModuleManager::loadChatWindowModule(){
	if(chatWindowModuleInfo != NULL){
		chatWindowModuleInfo->loadModule();
	}else{
		wxLogDebug(wxT("No ChatWindowModule found!"));
	}
}

void ModuleManager::initBuddyListModule(){
	if(buddyListModuleInfo){
		if(buddyListModuleInfo->isLoaded()){
			buddyListModuleInfo->initModule();
		}
	}
}

void ModuleManager::initUserInterfaceModule(){
	if(userInterfaceModuleInfo){
		if(userInterfaceModuleInfo->isLoaded()){
			userInterfaceModuleInfo->initModule();
		}
	}
}

void ModuleManager::initChatWindowModule(){
	if(chatWindowModuleInfo){
		if(chatWindowModuleInfo->isLoaded()){
			chatWindowModuleInfo->initModule();
		}
	}
}

void ModuleManager::destroyBuddyListModule(){
	if(buddyListModuleInfo){
		if(buddyListModuleInfo->isLoaded()){
			buddyListModuleInfo->destroyModule();
		}
	}
}

void ModuleManager::destroyUserInterfaceModule(){
	if(userInterfaceModuleInfo){
		if(userInterfaceModuleInfo->isLoaded()){
			userInterfaceModuleInfo->destroyModule();
		}
	}
}
void ModuleManager::destroyChatWindowModule(){
	if(chatWindowModuleInfo){
		if(chatWindowModuleInfo->isLoaded()){
			chatWindowModuleInfo->destroyModule();
		}
	}
}

size_t ModuleManager::loadAndInit(const wxString & interfaceClassName){

	size_t count = 0;

	std::vector<ModuleInfo*>::iterator i;
	for(i = modules.begin(); i != modules.end(); i++){
		ModuleInfo* m = *i;
		if(!m->isLoaded() && m->getInterfaceClassName() == interfaceClassName){
			m->loadModule();
			count++;
		}
	}

	for(i = modules.begin(); i != modules.end(); i++){
		ModuleInfo* m = *i;
		if(!m->isInited() && m->getInterfaceClassName() == interfaceClassName){
			if(m->isLoaded()){
				m->initModule();
			}
		}
	}
	//wxLogDebug(wxT("%i Modules loaded"), count);
	return count;
}

void ModuleManager::loadAndInitCoreInterfaceModules(){
	loadUserInterfaceModule();
	loadBuddyListModule();
	loadChatWindowModule();

	initUserInterfaceModule();
	initBuddyListModule();
	initChatWindowModule();

	loadAndInit(MODULE_INTERFACE_MODULE);
}

void ModuleManager::destroyCoreInterfaceModules(){
	destroyChatWindowModule();
	destroyBuddyListModule();
	destroyUserInterfaceModule();
}
void ModuleManager::destroyOtherModules(){
	std::vector<ModuleInfo*>::iterator i;
	for(i = modules.begin(); i != modules.end(); i++){
		ModuleInfo* m = *i;
		if(m->isLoaded()){
			m->destroyModule();
		}
	}
}


void ModuleManager::addAvailableModul(const wxString & moduleClassName, const wxString & interfaceClassName){

	ModuleInfo* info = new ModuleInfo(moduleClassName, interfaceClassName);

	if(interfaceClassName == MODULE_INTERFACE_USERINTERFACE){
		userInterfaceModuleInfo = info;
	}else if(interfaceClassName == MODULE_INTERFACE_BUDDYLIST){
		buddyListModuleInfo = info;
	}else if(interfaceClassName == MODULE_INTERFACE_CHATWINDOW){
		chatWindowModuleInfo = info;
	}

	modules.push_back(info);

}

void ModuleManager::addAvailableProtocol(const wxString & className){
	ProtocolInfo* info = new ProtocolInfo();
	info->className=className;
	protInfos.push_back(info);
}

iProtocol* ModuleManager::loadAndInitProtocolInstance(Account* account){

	std::vector<ProtocolInfo*>::iterator p;
	for(p = protInfos.begin(); p != protInfos.end(); p++){
		ProtocolInfo* info = *p;
		if(info->className == account->classname){
			return info->createAndInitInstance(account);
		}
	}
	return NULL;
}

iBuddyList* ModuleManager::getBuddyListModule(){
	if(buddyListModuleInfo != NULL){
		return dynamic_cast<iBuddyList*>(buddyListModuleInfo->getModule());
	}
	return NULL;
}
iUserInterface* ModuleManager::getUserInterfaceModule(){
	if(userInterfaceModuleInfo != NULL){
		return dynamic_cast<iUserInterface*>(userInterfaceModuleInfo->getModule());
	}
	return NULL;
}

iChatWindow* ModuleManager::getChatWindowModule(){
	if(chatWindowModuleInfo != NULL){
		return dynamic_cast<iChatWindow*>(chatWindowModuleInfo->getModule());
	}
	return NULL;
}

iModule* ModuleManager::getModuleByInterface(const wxString & interfaceClassName){
	std::vector<ModuleInfo*>::iterator i;
	for(i = modules.begin(); i != modules.end(); i++){
		ModuleInfo* m = *i;
		if(m->isLoaded() && m->getInterfaceClassName() == interfaceClassName){
			return m->getModule();
		}
	}
	return NULL;
}

iModule* ModuleManager::getModuleByClass(const wxString & className){
	std::vector<ModuleInfo*>::iterator i;
	for(i = modules.begin(); i != modules.end(); i++){
		ModuleInfo* m = *i;

		if(m->isLoaded() && m->getClassName() == className){
			return m->getModule();
		}
	}
	return NULL;
}



}
